package com.googlecode.cnasort.cc.rmi.server;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import org.apache.log4j.Logger;
//import com.googlecode.cnasort.cc.rmi.common.RMIFileLoaderConnector;
import com.googlecode.cnasort.cc.rmi.common.RMIFileLoaderConnectorV0;
import com.googlecode.cnasort.cc.rmi.common.ServerRmiStarter;
import com.googlecode.cnasort.cc.rmi.server.core.Log4JMessage;
import com.googlecode.cnasort.cc.rmi.server.core.Message;
import com.googlecode.cnasort.cc.rmi.server.core.RMIFileLoaderConnectorV0Impl;
import com.googlecode.cnasort.cc.rmi.server.ihm.ServerJFrame;

/**
 * com.googlecode.cnasort.cc.rmi.ExoRmiServer
 */
public class MyRmiServer extends ServerRmiStarter<RMIFileLoaderConnectorV0>
{
    private Message logger;

    public MyRmiServer( final Message message )
    {
        super( RMIFileLoaderConnectorV0.class, true );

        this.logger = message;
    }

//    public void startServer( final String serverName ) throws IOException
//    {
//        if( System.getSecurityManager() == null ) {
//            logger.info( "No SecurityManager");
//
//            try {
//                ClassLoader cl        = getClass().getClassLoader();
//                URL         policyURL = cl.getResource( "server.policy" );
//
//                System.setProperty( "java.security.policy", policyURL.toString() );
//                System.setSecurityManager( new RMISecurityManager() );
//
//                logger.info( "set new SecurityManager using : " + policyURL );
//                }
//            catch( Exception e ) {
//                logger.warn( "Error while setting SecurityManager", e );
//                }
//            }
//
//        try {
//            LocateRegistry.createRegistry( Registry.REGISTRY_PORT );
//            logger.info( "Server started" );
//            }
//        catch( RemoteException e ) {
//            // ignore;
//            logger.warn( "Server already started" );
//            }
//
//        try {
//            String serviceName = RMIFileLoaderConnector.SERVICE_NAME;
//            Remote cs          = RMIFileLoaderConnectorV0Impl.createRemove();
//            //Remote cs          = new RMIFileLoaderConnectorImpl().setServerName( serviceName );
//
//            Naming.rebind("//" + serverName + "/" + serviceName, cs);
//
//            logger.info("Server ready : " + serverName);
//            }
//        catch( MalformedURLException e ) {
//            logger.info( "MalformedURLException: " + e );
//
//            throw e;
//            }
//        catch( RemoteException e ) {
//            logger.info( "RemoteException: " + e );
//
//            throw e;
//            }
//    }

    public static void main( final String[] args ) throws IOException
    {
        if( args.length == 0 ) {
            ServerJFrame.main( args );
            }
        else {
            start( args );
        }
    }

    public static MyRmiServer start( Message message, String serverName )
    {
        MyRmiServer server  = new MyRmiServer( message );
        
        try {
            RMIFileLoaderConnectorV0Impl service = RMIFileLoaderConnectorV0Impl.createRemote();
            
            service.setMessage( message );
            
            server.exportObject(
        		service,
                RMIFileLoaderConnectorV0.SERVICE_NAME
                );
            }
        catch( RemoteException e ) {
            message.warn( "Startup error", e );
            }

        return server;
    }


    private static void start( final String...args ) throws IOException
    {
        final Logger        logger     = Logger.getLogger( MyRmiServer.class );
        final Message       message    = new Log4JMessage(logger);
        List<InetAddress>   addrList   = getEthernetInterfaces( message );
        String              serverName = "localhost";

        for( InetAddress addr : addrList ) {
            final String ip = addr.getHostName();

            if( ip.startsWith( "192.168.100" ) ) {
                serverName = ip;
                }
            }

       start( message, serverName );
     }

    private static List<InetAddress> getEthernetInterfaces( final Message message ) throws SocketException
    {
        final List<InetAddress> adresses = new ArrayList<>();

        for( final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces( ); interfaces.hasMoreElements(); ) {
            final NetworkInterface cur = interfaces.nextElement( );

            if( cur.isLoopback( ) ) {
                continue;
                }

            for( final InterfaceAddress addr : cur.getInterfaceAddresses( ) ) {
                final InetAddress inet_addr = addr.getAddress( );

                if( !( inet_addr instanceof Inet4Address ) ) {
                    continue;
                    }

                adresses.add( inet_addr );

                String address = inet_addr.getHostAddress();

                message.info(
                    "  interface: " + cur.getName() +
                    "  address: " + address +
                    "/" + addr.getNetworkPrefixLength( )
                    );

                message.info(
                    "  broadcast address: " + addr.getBroadcast().getHostAddress()
                    );
                }
            }

        return adresses;
    }
/*
    static class MyOutputStream extends OutputStream
    {
        private ByteArrayOutputStream out = new ByteArrayOutputStream();

        @Override
        public void write(int b) throws IOException {
            System.out.write(b);
            out.write(b);
        }

        @Override
        public void write(byte[] b) throws IOException {
            System.out.write(b);
            out.write(b);
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            System.out.write(b,off,len);
            out.write(b,off,len);
        }

        public byte[] toByteArray()
        {
            return out.toByteArray();
        }
    }*/
}
